package com.github.common.util.sercurity.encrypt;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

public class EncryptUtil {
    // 加密算法
    private static final String ALGORITHM = "AES";
    // 加密模式：CBC，填充方式：PKCS5Padding
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    // IV长度（AES块大小固定为16字节）
    private static final int IV_SIZE = 16;

    /**
     * 加密方法s
     *
     * @param plainText 明文
     * @param secretKey 密钥（必须16/24/32字节）
     * @return Base64编码的密文（包含IV）
     */
    public static String encrypt(String plainText, String secretKey) {
        try {
            // 验证密钥长度
            validateKey(secretKey);

            // 生成随机IV
            byte[] iv = new byte[IV_SIZE];
            new SecureRandom().nextBytes(iv);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            // 创建密钥规范
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

            // 执行加密
            byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));

            // 组合IV和密文
            byte[] combined = new byte[iv.length + encrypted.length];
            System.arraycopy(iv, 0, combined, 0, iv.length);
            System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);

            // 返回Base64编码结果
            return Base64.getEncoder().encodeToString(combined);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解密方法
     *
     * @param cipherText Base64编码的密文（包含IV）
     * @param secretKey  密钥（必须16/24/32字节）
     * @return 解密后的明文
     */
    public static String decrypt(String cipherText, String secretKey) {
        // 初始化解密器
        try {
            // 验证密钥长度
            validateKey(secretKey);

            // 解码Base64
            byte[] combined = Base64.getDecoder().decode(cipherText);

            // 分离IV和密文
            byte[] iv = new byte[IV_SIZE];
            byte[] encrypted = new byte[combined.length - IV_SIZE];
            System.arraycopy(combined, 0, iv, 0, iv.length);
            System.arraycopy(combined, iv.length, encrypted, 0, encrypted.length);

            // 创建密钥规范和IV
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

            // 执行解密
            byte[] decrypted = cipher.doFinal(encrypted);
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 验证密钥长度
     *
     * @param key 密钥字符串
     */
    private static void validateKey(String key) {
        if (key == null) throw new IllegalArgumentException("密钥不能为null");
        int len = key.getBytes(StandardCharsets.UTF_8).length;
        if (len != 16 && len != 24 && len != 32) {
            throw new IllegalArgumentException("密钥长度必须为16/24/32字节（当前：" + len + "字节）");
        }
    }

}